package com.gcosc.hly.codejava.service.impl;

import com.gcosc.hly.codejava.Utils.ClassRun.DynamicCompiler;
import com.gcosc.hly.codejava.entity.AnswerItem;
import com.gcosc.hly.codejava.entity.TopicResult;
import com.gcosc.hly.codejava.result.Code;
import com.gcosc.hly.codejava.service.TopicTestService;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

@Service
public class TopicTestServiceImpl implements TopicTestService {

    @Override
    public boolean execute(Class<?>[] paramsType, Object[] params, Object result, Object code) throws Exception {
        Class aClass = code.getClass();
        Method main = aClass.getMethod("main", paramsType);
        return myEq(main.invoke(code, params), result);
    }


    @Override
    public boolean myEq(Object o, Object j) {
        if (o == j){
            return true;
        }

        if (o.getClass().isArray()){
            return o instanceof int[] ? Arrays.equals((int[])o, (int[])j) :
                    o instanceof double[] ? Arrays.equals((double[])o, (double[])j) :
                            Arrays.equals((String[])o, (String[])j);
        }

        return o.equals(j);
    }

    public Class[] toClass(String[] split){
        Class[] paramsType = new Class[split.length];
        for (int i = 0; i < split.length; i++) {
            if (split[i].length() == 0){
                continue;
            }
            String s = split[i].split(":")[0];
            switch (s){
                case "int":
                    paramsType[i] = int.class;
                    break;
                case "double":
                    paramsType[i] = double.class;
                    break;
                case "String":
                    paramsType[i] = String.class;
                    break;
                case "int[]":
                    paramsType[i] = int[].class;
                    break;
                case "double[]":
                    paramsType[i] = double[].class;
                    break;
                case "String[]":
                    paramsType[i] = String[].class;
                    break;
            }
        }
        return paramsType;
    }

    public Object[] toObject(String[] split){
        Object[] params = new Object[split.length];
        for (int i = 0; i < split.length; i++) {
            if (split[i].length() == 0){
                continue;
            }
            String[] s = split[i].split(":");
            switch (s[0]){
                case "int":
                    params[i] = Integer.parseInt(s[1]);
                    break;
                case "double":
                    params[i] = Double.parseDouble(s[1]);
                    break;
                case "String":
                    params[i] = s[1];
                    break;
                case "int[]":
                    String[] ints = s[1].split(",");
                    int[] a = new int[ints.length];
                    for (int i1 = 0; i1 < ints.length; i1++) {
                        a[i1] = Integer.parseInt(ints[i1]);
                    }
                    params[i] = a;
                    break;
                case "double[]":
                    String[] doubles = s[1].split(",");
                    double[] aa = new double[doubles.length];
                    for (int i1 = 0; i1 < doubles.length; i1++) {
                        aa[i1] = Double.parseDouble(doubles[i1]);
                    }
                    params[i] = aa;
                    break;
                case "String[]":
                    params[i] = s[1].split(",");
                    break;
            }
        }
        return params;
    }

    @Override
    public boolean test(List<TopicResult> topicResult, AnswerItem answerItem) {

        DynamicCompiler dynamicCompiler = new DynamicCompiler();
        try {
            Class<?> aClass = dynamicCompiler
                    .compileToClass(
                            "com.gcosc.hly.codejava.service.impl.Test",
                            "package com.gcosc.hly.codejava.service.impl;\n\r" +
                    answerItem.getCode());

            Object code = aClass.newInstance();

            for (TopicResult result : topicResult){

                String[] split = result.getParams().split(";");

                Object[] params = toObject(split);

                Class[] paramsType = toClass(split);

                Object res = toObject(result.getResult().split(";"))[0];

                if (!execute(paramsType, params, res, code)){
                    return false;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            Code.BUSINESS_ERR(e.getMessage());
        }
        return true;
    }

}
